package FunctionsDifferentiation;

import java.util.ArrayList;
import java.util.LinkedList;

import Functions.*;


public class differentiation 
{
	
	private ParserImplementation function;
	
	public differentiation(ParserImplementation givenFunction)
	{
		function = givenFunction;
	}
	
	public Parser diff()
	{
		LinkedList<Element> terms = function.getFunction();
		for(int i=0;i<terms.size();i++)
		{
			
		}
		return null;
	}
	
	
	private int maxSize(double[][] function)
	{
		int numberOfZeros=0;
		for(int i=0;i<function.length;i++)
		{
			if(function[i][1]==0)
				numberOfZeros++;
		}
		return function.length-numberOfZeros;
	}
	
	private Element polynomialDiff(Polynomial polynomialTerm)
	{
		int maxSize = maxSize(polynomialTerm.getPoly());
		if(maxSize==0)
			return null;
		else
		{
			double[][] newPolynomial = new double[maxSize][];
			for(int i=0;i<maxSize;i++)
			{
				if(newPolynomial[i][1]!=0)
				{
					newPolynomial[i][0] = polynomialTerm.getPoly()[i][0]*polynomialTerm.getPoly()[i][1];
					newPolynomial[i][1] = polynomialTerm.getPoly()[i][1]-1;
				}
			}
			Polynomial diffPolynomial = new Polynomial(newPolynomial);
			ArrayList<Functions>  elements = new ArrayList<Functions>();
			elements.add(diffPolynomial);
			Element term = new Element(elements);
			return term;
		}
	}
	
	private Element sinDiff(Sin sinTerm)
	{
		ArrayList<Functions>  elements = new ArrayList<Functions>();
		Element diffPart = polynomialDiff(sinTerm.getFunction());
		if(diffPart == null)
			return null;
		else
		{
			if(sinTerm.getExp()!=1)
			{
				Polynomial powerPart = new Polynomial(0,sinTerm.getExp());
				Sin sinPart = new Sin(sinTerm.getFunction(),sinTerm.getExp()-1);
				elements.add(powerPart);
				elements.add(sinPart);
			}
			Cos trignoDiff = new Cos(sinTerm.getFunction(),1);
			elements.add(trignoDiff);
			elements.add(diffPart.getTerm().get(0));
			Element term = new Element(elements);
			return term;
		}
	}
	
	private Element cosDiff(Cos cosTerm)
	{
		ArrayList<Functions>  elements = new ArrayList<Functions>();
		Element diffPart = polynomialDiff(cosTerm.getFunction());
		if(diffPart==null)
			return null;
		else
		{
			if(cosTerm.getExp()!=1)
			{
				Polynomial powerPart = new Polynomial(0,cosTerm.getExp());
				Cos cosPart = new Cos(cosTerm.getFunction(),cosTerm.getExp()-1);
				elements.add(powerPart);
				elements.add(cosPart);
			}
			Sin trignoDiff = new Sin(cosTerm.getFunction(),1);
			elements.add(trignoDiff);
			elements.add(diffPart.getTerm().get(0));
			Element term = new Element(elements);
			return term;
		}
	}

	private Element eDiff(exp expTerm)
	{
		ArrayList<Functions>  elements = new ArrayList<Functions>();
		Element diffPart = polynomialDiff(expTerm.getFunction());
		if(diffPart==null)
			return null;
		else
		{
			exp newExp = expTerm;
			elements.add(newExp);
			elements.add(diffPart.getTerm().get(0));
			Element term = new Element(elements);
			return term;
		}
	}

}
